﻿using BLevy.Datos.Interfases;
using BLevy.Entidad;
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Dapper;
using DapperExtensions;
using System.ComponentModel;
using System.Data.SqlClient;

namespace BLevy.Datos.Repositories
{
    public interface ICuponRepository : IRepository<Cupon>
    {
        int GetNextNumero(int prefijo_id);
        int VerificarImpresionMensual(DateTime primerdiames, DateTime ultimodiames);
        IList<Cupon> FindAllPorFecha(DateTime fecha);
        IList<CuponDetalle> FindAllDetalles();
        IList<CuponDetalle> FindAllDetallesByIdCupon(int cupon_id);
        IList<CuponPrefijo> FindAllPrefijos();
        int AgregarPrefijo(CuponPrefijo prefijo);
        int EliminarPrefijo(int id);
        double CalcularImporteCupon(Cupon cupon);
        IList<Cupon> GetAllCuponesAImprimir();
        IList<Cupon> FindAllConSocio();
        int GenerarCupon(int socio_id, string numero_cupon, double total);
        CuponPrefijo GetPrefijoActivo();
        int AddNumeroCupon(CuponPrefijo prefijo, string numero);
        int ModifyNumeroCupon(CuponPrefijo prefijo, string numero);
        int AddDetalleCupon(int cupon_id, int periodosocio_id, double total);
        Cupon FindByNumero(string nro);
        IList<Cupon> FindAllCondicional(string numero_cupon, string numero_certificado, DateTime? desde, DateTime? hasta, int? formapago_id, int? zona_id);
        IList<Cupon> FindAllImpresionParcial(string nrocert_desde, string nrocert_hasta, int? localidad_id, int? zona_id, string letra_desde, string letra_hasta, string nrocupon_desde, string nrocupon_hasta);
        int PagoCupon(Cupon _cupon);
        IList<Cupon> FindAllCondicionalReporte(string numero_cupon, string numero_certificado, DateTime? desde, DateTime? hasta);
        IList<CuponDetalle> FindAllDetallesPagoByIdCupon(int cupon_id);
        string FindUltimoNumeroCupon(int prefijo_id);
        int SetNumeracionCupon(int prefijo_id, string numero);
        int ModificarNumeracionCupon(int prefijo_id, string numero);
        IList<Cupon> FindAllPorSocioId(int socio_id);
    }

    public class CuponRepository : ICuponRepository
    {

        protected readonly IDbConnection _db;

        public CuponRepository()
        {
            try
            {
                _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString());
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public IList<Cupon> FindAll()
        {
            string query = "SELECT * FROM CUPONES";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<Cupon>(query).ToList();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public IQueryable<Cupon> Find(System.Linq.Expressions.Expression<Func<Cupon, bool>> predicate)
        {
            throw new NotImplementedException();
        }

        public Cupon FindById(int id)
        {
            string query = "SELECT * FROM CUPONES WHERE ID = @id";
            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<Cupon>(query, new { id = id }).SingleOrDefault();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public Cupon FindByNumero(string nro)
        {
            string query = "SELECT * FROM CUPONES C INNER JOIN SOCIOS S ON C.SOCIO_ID = S.ID " +
                            "WHERE NUMERO LIKE @nro";
            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<Cupon, Socio, Cupon>(query,
                        (cupon, socio) =>
                        {
                            cupon.socio = socio;
                            return cupon;
                        }, new
                        {
                            nro = nro
                        }, splitOn: "id").SingleOrDefault();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public int Add(Cupon newEntity)
        {
            throw new NotImplementedException();
        }

        public int Remove(int id)
        {
            throw new NotImplementedException();
        }

        public int Modify(Cupon _cupon)
        {
            string query = "UPDATE CUPONES SET numero = @numero, socio_id = @socio_id, fecha_emision = @fecha_emision, total = @total, estado = @estado, transito = @transito " +
                            "WHERE id = @id";
            try
            {

                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Execute(query, new
                    {
                        id = _cupon.id,
                        numero = _cupon.numero,
                        socio_id = _cupon.socio_id,
                        fecha_emision = _cupon.fecha_emision,
                        total = _cupon.total,
                        estado = _cupon.estado,
                        transito = _cupon.transito
                    });
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public int GenerarCupon(int socio_id, string numero_cupon, double total)
        {
            string query = "INSERT INTO CUPONES (NUMERO, SOCIO_ID, FECHA_EMISION, TOTAL, ESTADO, TRANSITO) " +
                       "VALUES (@numero, @socio_id, @fecha_emision, @total, @estado, @transito);" +
                       "SELECT LAST_INSERT_ID();";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {

                    //inserto el cupon
                    return _db.Query<int>(query, new
                    {
                        numero = numero_cupon,
                        socio_id = socio_id,
                        fecha_emision = DateTime.Now,
                        total = total,
                        estado = "I",
                        transito = "I"
                    }).Single();


                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public int GenerarCupones(int socio_id, string numero_cupon, double total)
        {

            string query = "INSERT INTO CUPONES (NUMERO, SOCIO_ID, FECHA_EMISION, TOTAL, ESTADO, TRANSITO) " +
                        "VALUES (@numero, @socio_id, @fecha_emision, @total, @estado, @transito);" +
                        "SELECT LAST_INSERT_ID();";

            string query_detalle = "INSERT INTO CUPONESDETALLES (CUPON_ID, PERIODOSOCIO_ID, IMPORTE) " +
                                    "VALUES (@cupon_id, @periodosocio_id, @importe)";

            string query_numero = "INSERT INTO CUPONESNUMERACIONES (PREFIJO_ID, NUMERO) " +
                                "VALUES (@prefijo_id, @numero)";

            string query_numero_updt = "UPDATE CUPONESNUMERACIONES SET NUMERO = @numero " +
                                    "WHERE PREFIJO_ID = @prefijo_id";

            string query_next = "SELECT IFNULL(CAST(MAX(NUMERO) AS UNSIGNED), 0) FROM CUPONESNUMERACIONES " +
                                "WHERE PREFIJO_ID = @prefijo_id";

            string query_prefijo = "SELECT * FROM CUPONESPREFIJOS " +
                                    "WHERE ACTIVO = 1";

            int cupon_id = 0;
            bool resultado = true;

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {

                    return _db.Query<int>(query, new
                       {
                           numero = numero_cupon,
                           socio_id = socio_id,
                           fecha_emision = DateTime.Now,
                           total = total,
                           estado = "I",
                           transito = "E"
                       }).Single();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
                //_db.Open();
                //IDbTransaction transaction = _db.BeginTransaction();

                //SocioRepository _repository = new SocioRepository();
                //IList<Socio> SociosL = _repository.FindAllActivos();

                //foreach (Socio socio in SociosL)
                //{
                //    PeriodoRepository _repositoryPeriodo = new PeriodoRepository();
                //    PeriodoSocioRepository _repositoryPeriodoSocios = new PeriodoSocioRepository();
                //    IList<PeriodoSocio> periodo_socio = _repositoryPeriodoSocios.FindAllImpagosBySocioId(socio.id);

                //    //calculo el total del cupon
                //    decimal total = 0;
                //    foreach (PeriodoSocio _periodo in periodo_socio)
                //    {
                //        Periodo periodo = _repositoryPeriodo.FindById(_periodo.periodo_id);
                //        if (periodo.vencimiento_1 < DateTime.Now && _periodo.estado == "I")
                //        {
                //            total = total + (_periodo.importe + periodo.recargo);
                //        }
                //        else
                //        {
                //            total = total + _periodo.importe;
                //        }
                //    }

                    //obtengo el prefijo activo
                    //CuponPrefijo prefijo = _db.Query<CuponPrefijo>(query_prefijo).SingleOrDefault();

                    ////obtengo el ultimo numero de cupon
                    //int numero = _db.Query<int>(query_next, new { prefijo_id = prefijo.id }).Single();
                    //if (numero == 0)
                    //    numero = 1;
                    //else
                    //    numero = numero + 1;

                    //if (numero == 1)
                    //{
                    //    int filasAfectadas = _db.Execute(query_numero, new
                    //    {
                    //        prefijo_id = prefijo.id,
                    //        numero = String.Format("{0:00000000}", numero)
                    //    }, transaction);

                    //    if (filasAfectadas == 0)
                    //    {
                    //        cupon_id = 0;
                    //        transaction.Rollback();
                    //        break;
                    //    }
                    //}
                    //else
                    //{
                    //    int filasAfectadas = _db.Execute(query_numero_updt, new
                    //    {
                    //        prefijo_id = prefijo.id,
                    //        numero = String.Format("{0:00000000}", numero)
                    //    }, transaction);

                    //    if (filasAfectadas == 0)
                    //    {
                    //        cupon_id = 0;
                    //        transaction.Rollback();
                    //        break;
                    //    }
                    //}

                    //inserto el cupon
                   

                    //if (cupon_id > 0)
                    //{
                    //    //inserto el detalle del cupon
                    //    foreach (PeriodoSocio _periodo in periodo_socio)
                    //    {
                    //        int filasAfectadas = _db.Execute(query_detalle, new
                    //        {
                    //            cupon_id = cupon_id,
                    //            periodosocio_id = _periodo.id,
                    //            importe = _periodo.importe
                    //        }, transaction);

                    //        if (filasAfectadas == 0)
                    //        {
                    //            resultado = false;
                    //            break;
                    //        }
                    //    }
                    //}
                    //else
                    //{
                    //    transaction.Rollback();
                    //    cupon_id = 0;
                    //    break;
                    //}
                //}

                //if (resultado != false)
                //{
                //    transaction.Commit();
                //}
                //else
                //{
                //    transaction.Rollback();
                //    cupon_id = 0;
                //}
            //}

            //return cupon_id;
        }


        public int GetNextNumero(int prefijo_id)
        {
            string query = "SELECT IFNULL(CAST(MAX(NUMERO) AS UNSIGNED), 0) FROM CUPONESNUMERACIONES " +
                               "WHERE PREFIJO_ID = @prefijo_id";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    int numero = _db.Query<int>(query, new { prefijo_id = prefijo_id }).Single();
                    if (numero == 0)
                    {
                        numero = 1;
                    }
                    else
                    {
                        numero = numero + 1;
                    }
                    return numero;
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public int VerificarImpresionMensual(DateTime primerdiames, DateTime ultimodiames)
        {
            string query = "SELECT COUNT(*) FROM CUPONES " +
                            "WHERE FECHA_EMISION BETWEEN @primerdiames AND @ultimodiames";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<int>(query, new { primerdiames = primerdiames, ultimodiames = ultimodiames }).Single();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public IList<Cupon> FindAllPorFecha(DateTime fecha)
        {
            string query = "SELECT * FROM CUPONES " +
                "WHERE FECHA_GENERACION = @fecha";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<Cupon>(query, new { fecha = fecha }).ToList();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public IList<CuponDetalle> FindAllDetalles()
        {
            string query = "SELECT * FROM CUPONESDETALLES";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<CuponDetalle>(query).ToList();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }


        public IList<CuponPrefijo> FindAllPrefijos()
        {
            string query = "SELECT * FROM CUPONESPREFIJOS";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<CuponPrefijo>(query).ToList();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public int AgregarPrefijo(CuponPrefijo prefijo)
        {
            string query = "INSERT INTO CUPONESPREFIJOS (PREFIJO, ACTIVO) " +
                           "VALUES (@prefijo, @activo);" +
                           "SELECT LAST_INSERT_ID();";

            string query_activo = "UPDATE CUPONESPREFIJOS SET ACTIVO = 0 " +
                "WHERE ID <> @id";

            bool resultado = true;

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    _db.Open();
                    IDbTransaction transaction = _db.BeginTransaction();
                    //inserto el prefijo nuevo
                    int prefijo_id = _db.Query<int>(query, new { prefijo = prefijo.prefijo, activo = prefijo.activo }, transaction).Single();

                    //si el prefijo viene activo, desactivo todos menos el nuevo
                    if (prefijo.activo == 1)
                    {
                        int filasAfectadas = _db.Execute(query_activo, new { id = prefijo_id }, transaction);
                        if (filasAfectadas == 0)
                        {
                            resultado = false;
                        }
                    }

                    //si actualizo correctamente genero el commit
                    if (resultado == true)
                    {
                        transaction.Commit();
                    }
                    else // si no vuelvo atras la transaccion
                    {
                        transaction.Rollback();
                        prefijo_id = 0;
                    }

                    return prefijo_id;
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public int EliminarPrefijo(int id)
        {
            string query = "UPDATE CUPONESPREFIJOS SET ACTIVO = 0 " +
                            "WHERE ID = @id";
            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Execute(query, new { id = id });
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public double CalcularImporteCupon(Cupon cupon)
        {
            PeriodoSocioRepository _repositoryPeriodoSocio = new PeriodoSocioRepository();
            PeriodoRepository _repositoryPeriodo = new PeriodoRepository();
            double total = 0;

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {

                    foreach (CuponDetalle detalle in cupon.detalles)
                    {
                        PeriodoSocio periodoSocio = _repositoryPeriodoSocio.FindById(detalle.periodosocio_id);
                        Periodo periodo = _repositoryPeriodo.FindById(periodoSocio.periodo_id);
                        if (periodo.vencimiento_1 < cupon.fecha_emision && periodoSocio.estado == "I")
                        {
                            total = total + (periodoSocio.importe * periodo.recargo);
                        }
                        else
                        {
                            total = total + periodoSocio.importe;
                        }
                    }
                }
            }
            catch(Exception e)
            {
                throw e;
            }

            return total;
        }

        public IList<CuponDetalle> FindAllDetallesByIdCupon(int cupon_id)
        {
            string query = "SELECT * FROM CUPONESDETALLES D INNER JOIN CUPONES C ON D.CUPON_ID = C.ID " + 
                            "INNER JOIN PERIODOSSOCIOS S ON D.PERIODOSOCIO_ID = S.ID " + 
                            "INNER JOIN PERIODOS P ON S.PERIODO_ID = P.ID " + 
                            "WHERE CUPON_ID = @cupon_id";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<CuponDetalle, Cupon, PeriodoSocio, Periodo, CuponDetalle>(query,
                        (cupon_detalle, cupon, periodosocio, periodo) =>
                        {
                            cupon_detalle.cupon = cupon;
                            cupon_detalle.periodo = periodo;
                            return cupon_detalle;
                        }, new
                        {
                            cupon_id = cupon_id
                        }).ToList();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public IList<Cupon> GetAllCuponesAImprimir()
        {
            string query_fecha = "SELECT MAX(FECHA_EMISION) FROM CUPONES";

            string query = "SELECT * FROM CUPONES " +
                            "INNER JOIN SOCIOS ON SOCIOS.ID = CUPONES.SOCIO_ID " +
                            "INNER JOIN FORMASPAGO ON FORMASPAGO.ID = SOCIOS.FORMAPAGO_ID " +
                            "WHERE CUPONES.FECHA_EMISION = @fecha";

            try
            {

                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    DateTime ultima_fecha = _db.Query<DateTime>(query_fecha).Single();

                    return _db.Query<Cupon, Socio, FormaPago, Cupon>(query,
                        (cupon, socio, formapago) =>
                        {
                            cupon.socio = socio;
                            cupon.socio.formapago = formapago;
                            return cupon;
                        },
                            new { fecha = ultima_fecha }).ToList();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public IList<Cupon> FindAllConSocio()
        {
            string query = "SELECT * FROM CUPONES " +
                "INNER JOIN SOCIOS ON SOCIOS.ID = CUPONES.SOCIO_ID ";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<Cupon, Socio, Cupon>(query, (cupon, socio) =>
                    {
                        cupon.socio = socio;
                        return cupon;
                    }, splitOn: "id").ToList();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public CuponPrefijo GetPrefijoActivo()
        {
            string query = "SELECT * FROM CUPONESPREFIJOS " +
                                   "WHERE ACTIVO = 1";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<CuponPrefijo>(query).SingleOrDefault();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public int AddNumeroCupon(CuponPrefijo prefijo, string numero)
        {
            string query = "INSERT INTO CUPONESNUMERACIONES (PREFIJO_ID, NUMERO) " +
                                "VALUES (@prefijo_id, @numero)";
            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Execute(query, new { prefijo_id = prefijo.id, numero = numero });
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public int ModifyNumeroCupon(CuponPrefijo prefijo, string numero)
        {
            string query = "UPDATE CUPONESNUMERACIONES SET NUMERO = @numero " +
                                    "WHERE PREFIJO_ID = @prefijo_id";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Execute(query, new { prefijo_id = prefijo.id, numero = numero });
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public int AddDetalleCupon(int cupon_id, int periodo_id, double periodo_importe)
        {
            string query = "INSERT INTO CUPONESDETALLES (CUPON_ID, PERIODOSOCIO_ID, IMPORTE) " +
                                    "VALUES (@cupon_id, @periodosocio_id, @importe)";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Execute(query, new
                    {
                        cupon_id = cupon_id,
                        periodosocio_id = periodo_id,
                        importe = periodo_importe
                    });
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        //public DataTable ConvertToDataTable<T>(IList<T> data)
        //{
        //    PropertyDescriptorCollection properties =
        //       TypeDescriptor.GetProperties(typeof(T));
        //    DataTable table = new DataTable();
        //    foreach (PropertyDescriptor prop in properties)
        //        table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
        //    foreach (T item in data)
        //    {
        //        DataRow row = table.NewRow();
        //        foreach (PropertyDescriptor prop in properties)
        //            row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
        //        table.Rows.Add(row);
        //    }
        //    return table;
        //}


        public IList<Cupon> FindAllCondicional(string numero_cupon, string numero_certificado, DateTime? desde, DateTime? hasta, int? formapago_id, int? zona_id)
        {
            if (desde != null && hasta != null)
            {
                desde = desde.Value.AddDays(-1);
                hasta = hasta.Value.AddDays(1);
            }

            string query = "SELECT * FROM CUPONES " +
               "INNER JOIN SOCIOS ON SOCIOS.ID = CUPONES.SOCIO_ID " +
               "WHERE ((CUPONES.NUMERO LIKE CONCAT('%', @numero_cupon, '%')) OR (@numero_cupon IS NULL)) " +
               "AND ((SOCIOS.FORMAPAGO_ID = @formapago_id) OR (@formapago_id IS NULL)) " + 
               "AND ((SOCIOS.ZONA_ID = @zona_id) OR (@zona_id IS NULL)) " +
               "AND ((SOCIOS.NUMERO_CERTIFICADO LIKE CONCAT('%', @numero_certificado, '%')) OR (@numero_certificado IS NULL)) " +
               "AND ((CUPONES.FECHA_EMISION BETWEEN @desde AND @hasta) OR ((@desde IS NULL) OR (@hasta IS NULL))) " +
               "ORDER BY CUPONES.FECHA_EMISION DESC";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<Cupon, Socio, Cupon>(query, (cupon, socio) =>
                    {
                        cupon.socio = socio;
                        return cupon;
                    }, new
                    {
                        numero_cupon = numero_cupon,
                        numero_certificado = numero_certificado,
                        desde = desde,
                        hasta = hasta,
                        formapago_id = formapago_id,
                        zona_id = zona_id
                    }, splitOn: "id").ToList();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }


        public IList<Cupon> FindAllImpresionParcial(string nrocert_desde, string nrocert_hasta, int? localidad_id, int? zona_id, string letra_desde, string letra_hasta, string nrocupon_desde, string nrocupon_hasta)
        {
             string query_fecha = "SELECT MAX(FECHA_EMISION) FROM CUPONES";

             string query = "SELECT * FROM CUPONES " +
                             "INNER JOIN SOCIOS ON SOCIOS.ID = CUPONES.SOCIO_ID " +
                             "INNER JOIN FORMASPAGO ON FORMASPAGO.ID = SOCIOS.FORMAPAGO_ID " +
                             "WHERE (CUPONES.FECHA_EMISION = @fecha) " +
                             "AND ((SOCIOS.NUMERO_CERTIFICADO BETWEEN @certificado_desde AND @certificado_hasta) OR ((@certificado_desde IS NULL) OR (@certificado_hasta IS NULL))) " +
                             "AND ((SOCIOS.LOCALIDAD_ID = @localidad_id) OR (@localidad_id IS NULL)) " +
                             "AND ((SOCIOS.ZONA_ID = @zona_id) OR (@zona_id IS NULL)) " +
                             "AND ((CUPONES.NUMERO BETWEEN @numero_desde AND @numero_hasta) OR ((@numero_desde IS NULL) OR (@numero_hasta IS NULL))) " +
                             "AND ((SOCIOS.APELLIDO BETWEEN @letra_desde AND @letra_hasta) OR ((@letra_desde IS NULL) OR (@letra_hasta IS NULL))) " +
                             "ORDER BY SOCIOS.APELLIDO ASC";

             try
             {
                 using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                 {
                     DateTime ultima_fecha = _db.Query<DateTime>(query_fecha).Single();

                     return _db.Query<Cupon, Socio, FormaPago, Cupon>(query,
                         (cupon, socio, formapago) =>
                         {
                             cupon.socio = socio;
                             cupon.socio.formapago = formapago;
                             return cupon;
                         },
                             new
                             {
                                 fecha = ultima_fecha,
                                 certificado_desde = nrocert_desde,
                                 certificado_hasta = nrocert_hasta,
                                 localidad_id = localidad_id,
                                 zona_id = zona_id,
                                 numero_desde = nrocupon_desde,
                                 numero_hasta = nrocupon_hasta,
                                 letra_desde = letra_desde,
                                 letra_hasta = letra_hasta
                             }).ToList();
                 }
             }
             catch (Exception e)
             {
                 throw e;
             }
        }

        public int PagoCupon(Cupon _cupon)
        {
            string query = "UPDATE CUPONES SET estado = @estado, transito = @transito " +
                            "WHERE id = @id";

            string queryPeriodos = "UPDATE PERIODOSSOCIOS SET estado = @estado WHERE id = @id";

            int resultadoCupones = 0;
            int resultadoPeriodos = 0;
            int resultado = 0;


            using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
            {
                _db.Open();
                try
                {
                    foreach (CuponDetalle _detalle in _cupon.detalles)
                    {
                        resultadoPeriodos = _db.Execute(queryPeriodos, new
                        {
                            id = _detalle.periodosocio_id,
                            estado = _cupon.estado
                        });

                        if (resultadoPeriodos > 0)
                        {
                            //modifico el estado del cupon
                            resultadoCupones = _db.Execute(query, new
                            {
                                id = _detalle.cupon.id,
                                estado = _cupon.estado,
                                transito = _cupon.transito
                            });

                            if (resultadoCupones > 0)
                            {

                                resultado = resultadoCupones;
                            }
                            else
                            {
                                resultado = 0;
                                break;
                            }
                        }
                        else
                        {
                            resultado = 0;
                            break;
                        }
                    }
                }
                catch (Exception e)
                {
                    resultado = 0;
                    throw e;
                }
            }

            return resultadoCupones;
        }



        public IList<Cupon> FindAllCondicionalReporte(string numero_cupon, string numero_certificado, DateTime? desde, DateTime? hasta)
        {
            if (desde != null && hasta != null)
            {
                desde = desde.Value.AddDays(-1);
                hasta = hasta.Value.AddDays(1);
            }

            string query = "SELECT * FROM CUPONES " +
               "INNER JOIN SOCIOS ON SOCIOS.ID = CUPONES.SOCIO_ID " +
               "WHERE ((CUPONES.NUMERO LIKE CONCAT('%', @numero_cupon, '%')) OR (@numero_cupon IS NULL)) " +
               "AND ((SOCIOS.NUMERO_CERTIFICADO = @numero_certificado) OR (@numero_certificado IS NULL)) " +
               "AND ((CUPONES.FECHA_EMISION BETWEEN @desde AND @hasta) OR ((@desde IS NULL) OR (@hasta IS NULL))) " +
               "ORDER BY CUPONES.FECHA_EMISION DESC";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<Cupon, Socio, Cupon>(query, (cupon, socio) =>
                    {
                        cupon.socio = socio;
                        return cupon;
                    }, new
                    {
                        numero_cupon = numero_cupon,
                        numero_certificado = numero_certificado,
                        desde = desde,
                        hasta = hasta
                    }, splitOn: "id").ToList();
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }




        public IList<CuponDetalle> FindAllDetallesPagoByIdCupon(int cupon_id)
        {
            string query = "SELECT * FROM CUPONESDETALLES D INNER JOIN CUPONES C ON D.CUPON_ID = C.ID " +
                            "INNER JOIN PERIODOSSOCIOS S ON D.PERIODOSOCIO_ID = S.ID " +
                            "INNER JOIN PERIODOS P ON S.PERIODO_ID = P.ID " +
                            "WHERE D.PERIODOSOCIO_ID IN (SELECT PERIODOSOCIO_ID FROM CUPONESDETALLES WHERE cupon_id = @cupon_id) " +
                            "AND CUPON_ID <= @cupon_id AND C.ESTADO = 'I'";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<CuponDetalle, Cupon, PeriodoSocio, Periodo, CuponDetalle>(query,
                        (cupon_detalle, cupon, periodosocio, periodo) =>
                        {
                            cupon_detalle.cupon = cupon;
                            cupon_detalle.periodo = periodo;
                            return cupon_detalle;
                        }, new
                        {
                            cupon_id = cupon_id
                        }).ToList();
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }


        public string FindUltimoNumeroCupon(int prefijo_id)
        {
            string query = "SELECT COALESCE(MAX(NUMERO), 1) FROM CUPONESNUMERACIONES " +
                "WHERE PREFIJO_ID = @prefijo_id";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<string>(query, new { prefijo_id = prefijo_id }).Single();
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }


        public int SetNumeracionCupon(int prefijo_id, string numero)
        {
            string query = "INSERT INTO CUPONESNUMERACIONES(PREFIJO_ID, NUMERO) VALUES(@prefijo_id, @numero)";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Execute(query, new { prefijo_id = prefijo_id, numero = numero });
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public int ModificarNumeracionCupon(int prefijo_id, string numero)
        {
            string query = "UPDATE CUPONESNUMERACIONES SET NUMERO = @numero " +
                "WHERE PREFIJO_ID = @prefijo_id";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Execute(query, new { prefijo_id = prefijo_id, numero = numero });
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }


        public IList<Cupon> FindAllPorSocioId(int socio_id)
        {
            string query = "SELECT * FROM CUPONES WHERE SOCIO_ID = @socio_id";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<Cupon>(query, new { socio_id = socio_id }).ToList();
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }
    }
}
